﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SemanticEx.Tests
{
	[TestClass]
	public class BuilderTests
	{
		[TestMethod]
		public void Can_build_number_range()
		{
			Assert.AreEqual("[0-9]", new RegexBuilder()
				.Range('0', '9')
				.Build());
		}

		[TestMethod]
		public void Can_build_repeating_number_range()
		{
			Assert.AreEqual("[0-9]{5}", new RegexBuilder()
				.Range('0', '9').Repeat(5)
				.Build());
		}

		[TestMethod]
		public void Can_build_empty_group()
		{
			Assert.AreEqual("[0-9]{5}()", new RegexBuilder()
				.Range('0', '9').Repeat(5)
				.BeginGroup.EndGroup
				.Build());
		}

		[TestMethod]
		public void Can_build_character_collection()
		{
			Assert.AreEqual(@"[0-9]{5}([\-\s])", new RegexBuilder()
				.Range('0', '9').Repeat(5)
				.BeginGroup.Collection('-', ' ').EndGroup
				.Build());
		}

		[TestMethod]
		public void Can_build_zip_code()
		{
			Assert.Fail("Not implemented yet.");
		}
	}

	public class RegexBuilder
	{
		public RangeBuilder Range(char first, char last)
		{
			return new RangeBuilder(first, last);
		}
	}

	public class RangeBuilder
	{
		internal RangeBuilder(char first, char last)
		{
			First = first;
			Last = last;
		}

		public char First { get; set; }

		public char Last { get; set; }

		public RepeatBuilder Repeat(int count)
		{
			return new RepeatBuilder(Build(), count);
		}

		public string Build()
		{
			return string.Format("[{0}-{1}]", First, Last);
		}
	}

	public class RepeatBuilder
	{
		internal RepeatBuilder(string regex, int count)
		{
			Regex = regex;
			Count = count;
		}

		private string Regex { get; set; }

		public int Count { get; set; }

		public GroupBuilder BeginGroup
		{
			get
			{
				return new GroupBuilder(Build());
			}
		}

		public string Build()
		{
			return string.Format("{0}{{{1}}}", Regex, Count);
		}
	}

	public class GroupBuilder
	{
		internal GroupBuilder(string regex)
		{
			Regex = regex;
		}

		private string Regex { get; set; }

		public GroupBuilder EndGroup
		{
			get
			{
				return new GroupBuilder(string.Format("{0}()", Build()));
			}
		}

		public CollectionBuilder Collection(params char[] parms)
		{
			return new CollectionBuilder(Build(), parms);
		}

		public string Build()
		{
			return Regex;
		}
	}

	public class CollectionBuilder
	{
		public CollectionBuilder(string regex, IEnumerable<char> parms)
		{
			Regex = regex;
			Parameters = new List<char>(parms);
		}

		private string Regex { get; set; }

		public List<char> Parameters { get; private set; }

		public GroupBuilder EndGroup
		{
			get
			{
				throw new NotImplementedException();
			}
		}

		public string Build()
		{
			return string.Format("{0}[{1}]", Regex, string.Join(",", Parameters.Select(x => Process(x))));
		}

		private string Process(char ch)
		{
			switch (ch)
			{
				case ' ':
					return @"\s";
				case '-':
					return @"\-";
				default:
					return ch.ToString();
			}
		}
	}
}